home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / TURB_VIS / TVDMX / TVDMXBUF.PAS < prev    next >
Pascal/Delphi Source File  |  1994-06-20  |  21KB  |  875 lines

  1.  
  2. {■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■}
  3. {                            }
  4. {    tvDMXBUF  --Buffered Data Editing Unit        }
  5. {    tvDMX      --data editing project (ver 2.x)    }
  6. {                            }
  7. {    Copyright (c) 1992,94    Randolph Beck        }
  8. {                P.O. Box  56-0487    }
  9. {                Orlando, FL 32856    }
  10. {                CIS:  72361,753        }
  11. {                            }
  12. {■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■}
  13.  
  14. Unit tvDMXBUF;
  15.  
  16. {$B-,D+,R-,O+,X+,V- }
  17.  
  18. interface
  19.  
  20. uses
  21.     Objects, Drivers, Views, Dialogs, App, MsgBox,
  22.     RSet, DmxGizma, tvDMX, StdDMX;
  23.  
  24. const
  25.     EmptySlot    =  -1;
  26.  
  27. type
  28.     PSlot    = ^TSlot;
  29.     TSlot    =  RECORD
  30.     Data    : pointer;
  31.     RowNum    : longint;
  32.     end;
  33.  
  34.  
  35.     PRowSlots    = ^TRowSlots;
  36.     TRowSlots    =  array[0..99] of TSlot;
  37.  
  38.  
  39.     PDmxEditBuf     = ^TDmxEditBuf;
  40.     PDmxStreamBuf   = ^TDmxStreamBuf;
  41.     PDmxExpBuf        = ^TDmxExpBuf;
  42.     PDmxExpRecInd   = ^TDmxExpRecInd;
  43.     PDmxBufWin        = ^TDmxBufWin;
  44.     PDmxExpBufWin   = ^TDmxExpBufWin;
  45.     PDmxEditRecBuf  = ^TDmxEditRecBuf;
  46.  
  47.  
  48.     TDmxEditBuf   =  OBJECT(TDmxEditor)
  49.     Expandable    :  boolean;
  50.     Appending    :  boolean;
  51.     NumSlots    :  integer;
  52.     KeyFields    :  set of byte;
  53.     KeyAltered    :  boolean;
  54.     StepMode    :  boolean;
  55.       constructor Load(var S: TStream);
  56.       function  BufValid : boolean;  VIRTUAL;
  57.       function    DataAt(RecNum: integer)  : pointer;  VIRTUAL;
  58.       procedure DeleteRec;  VIRTUAL;
  59.       procedure DoneStruct;  VIRTUAL;
  60.       function    ErrorFunc : boolean;  VIRTUAL;
  61.       procedure EvaluateField;    VIRTUAL;
  62.       procedure EvaluateRecord;  VIRTUAL;
  63.       procedure HandleEvent(var Event: TEvent);  VIRTUAL;
  64.       procedure InitStruct(var ATemplate );  VIRTUAL;
  65.       procedure LoadStruct(var S: TStream);  VIRTUAL;
  66.       procedure MakeSlots;
  67.       function    ReadRec(var RecData ) : boolean;  VIRTUAL;
  68.       function    RecordLimit : longint;    VIRTUAL;
  69.       procedure ResetSize;
  70.       procedure ResetSlots;
  71.       function    SeekRec(RecNum: longint) : boolean;  VIRTUAL;
  72.       function    SeekEnd : boolean;  VIRTUAL;
  73.       procedure SetState(AState: word; Enable: boolean);  VIRTUAL;
  74.       procedure SetUpRecord;  VIRTUAL;
  75.       procedure Store(var S: TStream);
  76.       function    Valid(Command: word) : boolean;  VIRTUAL;
  77.       function    WriteRec(var RecData ) : boolean;  VIRTUAL;
  78.       procedure ZeroizeField(Whole: boolean; Field: pDMXfieldrec);  VIRTUAL;
  79.       procedure ZeroizeRecord;    VIRTUAL;
  80.       private
  81.     RowSlot        :  PRowSlots;
  82.     NewRecord    :  boolean;  { indicates this is a new record }
  83.     end;
  84.  
  85.  
  86.     TDmxStreamBuf =  OBJECT(TDmxEditBuf)
  87.     Prefix        :  pointer;
  88.     PrefixSize    :  integer;
  89.       function    ErrorFunc : boolean;  VIRTUAL;
  90.       procedure LoadStruct(var S: TStream);  VIRTUAL;
  91.       function    ReadRec(var RecData ) : boolean;  VIRTUAL;
  92.       function    RecordLimit : longint;    VIRTUAL;
  93.       function    SeekEnd : boolean;  VIRTUAL;
  94.       function    SeekRec(RecNum: longint) : boolean;  VIRTUAL;
  95.       procedure StoreStruct(var S: TStream);  VIRTUAL;
  96.       function    WriteRec(var RecData ) : boolean;  VIRTUAL;
  97.     end;
  98.  
  99.  
  100.     TDmxExpBuf      =  OBJECT(TDmxStreamBuf)
  101.       procedure InitData(var AData );  VIRTUAL;
  102.     end;
  103.  
  104.  
  105.     TDmxExpRecInd =  OBJECT(TDmxRecInd)
  106.       procedure Draw;  VIRTUAL;
  107.     end;
  108.  
  109.  
  110.     TDmxBufWin      =  OBJECT(TDmxWindow)
  111.       procedure InitDMX(ATemplate: string;  var AData;
  112.             ALabels,ARecInd: PDmxLink;
  113.             BSize: longint);  VIRTUAL;
  114.     end;
  115.  
  116.  
  117.     TDmxExpBufWin =  OBJECT(TDmxWindow)
  118.       procedure InitDMX(ATemplate: string;  var AData;
  119.             ALabels,ARecInd: PDmxLink;
  120.             BSize: longint);  VIRTUAL;
  121.       function    NewRecInd(Len: integer)  : PDmxLink;  VIRTUAL;
  122.     end;
  123.  
  124.  
  125.     TDmxEditRecBuf  =  OBJECT(TDmxEditBuf)
  126.     RecPosition    : longint;
  127.       function    AppendRec(var RecData ) : boolean;  VIRTUAL;
  128.       function    FirstRec : boolean;  VIRTUAL;
  129.       procedure InitData(var AData );  VIRTUAL;
  130.       function    LastRec : boolean;  VIRTUAL;
  131.       function    NextRec : boolean;  VIRTUAL;
  132.       function    PrevRec : boolean;  VIRTUAL;
  133.       function    SeekEnd : boolean;  VIRTUAL;
  134.       function    SeekRec(RecNum: longint) : boolean;  VIRTUAL;
  135.       function    UpdateRec(var RecData ) : boolean;  VIRTUAL;
  136.       function    WriteRec(var RecData ) : boolean;  VIRTUAL;
  137.     end;
  138.  
  139.  
  140.   procedure RegisterTVDMXBUF;
  141.  
  142.  
  143. const
  144.     RDmxStreamBuf    :  TStreamRec =(
  145.     ObjType:   rnDmxStreamBuf;
  146.     VmtLink:   ofs(TypeOf(TDmxStreamBuf)^);
  147.     Load:       @TDmxStreamBuf.Load;
  148.     Store:       @TDmxStreamBuf.Store
  149.       );
  150.  
  151.     RDmxExpBuf        :  TStreamRec =(
  152.     ObjType:   rnDmxExpBuf;
  153.     VmtLink:   ofs(TypeOf(TDmxExpBuf)^);
  154.     Load:       @TDmxExpBuf.Load;
  155.     Store:       @TDmxExpBuf.Store
  156.       );
  157.  
  158.     RDmxExpRecInd    :  TStreamRec =(
  159.     ObjType:   rnDmxExpRecInd;
  160.     VmtLink:   ofs(TypeOf(TDmxExpRecInd)^);
  161.     Load:       @TDmxExpRecInd.Load;
  162.     Store:       @TDmxExpRecInd.Store
  163.       );
  164.  
  165.     RDmxBufWin        :  TStreamRec =(
  166.     ObjType:   rnDmxBufWin;
  167.     VmtLink:   ofs(TypeOf(TDmxBufWin)^);
  168.     Load:       @TDmxBufWin.Load;
  169.     Store:       @TDmxBufWin.Store
  170.       );
  171.  
  172.     RDmxExpBufWin    :  TStreamRec =(
  173.     ObjType:   rnDmxExpBufWin;
  174.     VmtLink:   ofs(TypeOf(TDmxExpBufWin)^);
  175.     Load:       @TDmxExpBufWin.Load;
  176.     Store:       @TDmxExpBufWin.Store
  177.       );
  178.  
  179.  
  180. implementation
  181.  
  182.   { ══ TDmxEditBuf ═══════════════════════════════════════════════════════ }
  183.  
  184.  
  185. constructor TDmxEditBuf.Load(var S : TStream);
  186. begin
  187.   TDmxEditor.Load(S);
  188.   S.Read(KeyFields,  sizeof(KeyFields));
  189.   S.Read(Expandable, sizeof(Expandable));
  190.   S.Read(StepMode,   sizeof(StepMode));
  191. end;
  192.  
  193.  
  194. function  TDmxEditBuf.BufValid : boolean;
  195. begin
  196.   BufValid := TRUE
  197. end;
  198.  
  199.  
  200. function  TDmxEditBuf.DataAt(RecNum: integer) : pointer;
  201. var  Slot    : integer;
  202.      LRecNum    : longint;
  203.     function  SeekOK : boolean;
  204.     begin
  205.       If Expandable and (LRecNum >= RecordLimit) then
  206.     begin
  207.     NewRecord := TRUE;
  208.     SeekOK      := TRUE;
  209.     end
  210.        else
  211.     SeekOK := SeekRec(LRecNum);
  212.     end;
  213. begin
  214.   If (not InitValid) or (NumSlots = 0) or (RecordSize = 0) then
  215.     begin
  216.     Locked := TRUE;
  217.     DataAt := nil;
  218.     Exit;
  219.     end;
  220.   LRecNum := RecNum;
  221.   LRecNum := LRecNum + BaseRecord;
  222.   Slot    := LRecNum mod NumSlots;
  223.   NewRecord := FALSE;
  224.   If (RowSlot^[Slot].RowNum <> LRecNum) then
  225.     begin
  226.     FillChar(RowSlot^[Slot].Data^, RecordSize, 0);
  227.     RowSlot^[Slot].RowNum := LRecNum;
  228.     Repeat
  229.     Until (SeekOK and (NewRecord or ReadRec(RowSlot^[Slot].Data^)))
  230.     or ErrorFunc;
  231.     end;
  232.   DataAt := RowSlot^[Slot].Data;
  233. end;
  234.  
  235.  
  236. procedure TDmxEditBuf.DeleteRec;
  237. { pseudo-abstract virtual method to delete the record }
  238. begin
  239.   { override this method completely if you are removing a row too }
  240.   Appending := FALSE;
  241.   RecordAltered := TRUE;
  242. end;
  243.  
  244.  
  245. procedure TDmxEditBuf.DoneStruct;
  246. var i : integer;
  247. begin
  248.   If (RowSlot <> nil) then
  249.     begin
  250.     For i := 0 to pred(NumSlots) do
  251.       If (RowSlot^[i].Data <> nil) then FreeMem(RowSlot^[i].Data, RecordSize);
  252.     FreeMem(RowSlot, NumSlots * sizeof(TSlot));
  253.     RowSlot  := nil;
  254.     NumSlots := 0;
  255.     end;
  256.   TDmxEditor.DoneStruct;
  257. end;
  258.  
  259.  
  260. function  TDmxEditBuf.ErrorFunc : boolean;
  261. { pseudo-abstract method to handle access errors }
  262. begin
  263.  { This method should take care of the error
  264.    and return TRUE if the error can be ignored
  265.    or FALSE if the operation should be repeated. }
  266.  
  267.   ErrorFunc := (SystemError(14, 0) = 1);
  268. end;
  269.  
  270.  
  271. procedure TDmxEditBuf.EvaluateField;
  272. begin
  273.   If FieldAltered and (CurrentField^.fieldnum in KeyFields) then KeyAltered := TRUE;
  274.   TDmxEditor.EvaluateField;
  275. end;
  276.  
  277.  
  278. procedure TDmxEditBuf.EvaluateRecord;
  279. var  L : longint;
  280.     function  DoWrite : boolean;
  281.     begin
  282.       DoWrite := WriteRec(RowSlot^[CurrentRecord mod NumSlots].Data^);
  283.     end;
  284. begin
  285.   If RecordAltered then
  286.     begin
  287.     RecordAltered := FALSE;
  288.     If Appending then
  289.       begin
  290.       Repeat until (SeekEnd and DoWrite) or ErrorFunc;
  291.       ResetSize;
  292.       Appending := FALSE;
  293.       end
  294.     else
  295.     If StepMode then
  296.       begin
  297.       Repeat until DoWrite or ErrorFunc;
  298.       end
  299.      else
  300.       begin
  301.       L := CurrentRecord;
  302.       L := L + BaseRecord;
  303.       Repeat until (SeekRec(L) and DoWrite) or ErrorFunc;
  304.       end;
  305.     end;
  306.   TDmxEditor.EvaluateRecord;
  307.   If KeyAltered or not BufValid then
  308.     begin
  309.     KeyAltered := FALSE;
  310.     ResetSlots;
  311.     DrawView;
  312.     Message(Owner, evBroadcast, cmDMX_DrawData, WorkingData);
  313.     end;
  314. end;
  315.  
  316.  
  317. procedure TDmxEditBuf.HandleEvent(var Event: TEvent);
  318. var  RS,FS : boolean;
  319. begin
  320.   With Event do
  321.     If (What and evMessage <> 0) and (NumSlots > 0) and
  322.     (((Command = cmDMX_DrawData) and (WorkingData = InfoPtr))
  323.        or
  324.      ((Command = cmDMX_Draw)
  325.     and (InfoPtr <> @Self)
  326.     and (PDmxScroller(InfoPtr)^.WorkingData = WorkingData)))
  327.      then
  328.       begin
  329.       If Vidis then Exit;
  330.       RS := RecordSelected;
  331.       FS := FieldSelected;
  332.       If RS then
  333.     begin
  334.     If FS then EvaluateField;
  335.     EvaluateRecord;
  336.     end;
  337.       ResetSlots;
  338.       end
  339.      else
  340.       RS := FALSE;
  341.   TDmxEditor.HandleEvent(Event);
  342.   If RS then
  343.     begin
  344.     SetupRecord;
  345.     If FS then SetupField;
  346.     end;
  347. end;
  348.  
  349.  
  350. procedure TDmxEditBuf.InitStruct(var ATemplate );
  351. begin
  352.   TDmxEditor.InitStruct(ATemplate);
  353.   MakeSlots;
  354. end;
  355.  
  356.  
  357. procedure TDmxEditBuf.LoadStruct(var S: TStream);
  358. begin
  359.   TDmxEditor.LoadStruct(S);
  360.   MakeSlots;
  361. end;
  362.  
  363.  
  364. procedure TDmxEditBuf.MakeSlots;
  365. var i  : integer;
  366. begin
  367.   If InitValid and (RecordSize > 0) then
  368.     begin
  369.     NumSlots := ScreenHeight;
  370.     If (HiResScreen and (NumSlots < 30)) then NumSlots := 46;
  371.     If (NumSlots < Size.Y) then NumSlots := Size.Y;
  372.     GetMem(RowSlot, NumSlots * sizeof(TSlot));
  373.     fillchar(RowSlot^, NumSlots * sizeof(TSlot), 0);
  374.     For i := 0 to pred(NumSlots) do
  375.       begin
  376.       If ((MaxAvail shr 4) > RecordSize) then
  377.     begin
  378.     RowSlot^[i].RowNum := EmptySlot;
  379.     GetMem(RowSlot^[i].Data, RecordSize);
  380.     end
  381.        else
  382.     InitValid := FALSE;
  383.       end;
  384.     end;
  385. end;
  386.  
  387.  
  388. function  TDmxEditBuf.ReadRec(var RecData ) : boolean;
  389. { abstract virtual method to read a record }
  390. begin
  391.   Abstract;
  392.  { This method should read a record and return TRUE if there is no error. }
  393. end;
  394.  
  395.  
  396. function  TDmxEditBuf.RecordLimit : longint;
  397. { pseudo-abstract method returns the maximum number of records available }
  398. var  L : longint;
  399. begin
  400.   L := TDmxEditor.RecordLimit;
  401.   If Expandable and (L > 0) then Dec(L);
  402.   RecordLimit := L;
  403. end;
  404.  
  405.  
  406. procedure TDmxEditBuf.ResetSize;
  407. var  Recs,RecSize : longint;
  408.      A          : string;
  409. begin
  410.   Recs := RecordLimit;
  411.   If (Recs > 32766) then Recs := 32766;
  412.   If Expandable and (Recs < 32766) then Inc(Recs);
  413.   If (Recs < 0) then Recs := 0;
  414.   RecSize := RecordSize;
  415.   If (Recs * RecSize <> DataBlockSize) then
  416.     begin
  417.     DataBlockSize := Recs * RecSize;
  418.     SetLimit(Limit.X, Recs);
  419.     If (succ(CurrentRecord) > Recs) then CurrentRecord := Recs - 1;
  420.     ResetSlots;
  421.     end;
  422. end;
  423.  
  424.  
  425. procedure TDmxEditBuf.ResetSlots;
  426. var  i : integer;
  427. begin
  428.   If (NumSlots > 0) then
  429.     For i := 0 to pred(NumSlots) do RowSlot^[i].RowNum := EmptySlot;
  430. end;
  431.  
  432.  
  433. function  TDmxEditBuf.SeekEnd : boolean;
  434. { pseudo-abstract method used for expandable databases }
  435. begin
  436.  { This method should seek to the end of the database, and
  437.    return TRUE if there is no error.  Many database tools
  438.    will just require that you clear its record buffer.
  439.    The default here is to seek to the limit using method SeekRec().
  440.   }
  441.   SeekRec(RecordLimit);
  442.   SeekEnd := TRUE;
  443. end;
  444.  
  445.  
  446. function  TDmxEditBuf.SeekRec(RecNum: longint) : boolean;
  447. { abstract virtual method to seek to the record position }
  448. begin
  449.   Abstract;
  450.  { This method should seek to the given record
  451.    number, and return TRUE if there is no error.
  452.   }
  453. end;
  454.  
  455.  
  456. procedure TDmxEditBuf.SetState(AState: word; Enable: boolean);
  457. begin
  458.   If Enable and (AState and sfActive <> 0) and (not RecordSelected) and
  459.      Expandable and (CurrentField <> nil) then
  460.     ResetSize;
  461.   TDmxEditor.SetState(AState, Enable);
  462. end;
  463.  
  464.  
  465. procedure TDmxEditBuf.SetUpRecord;
  466. begin
  467.   If (NumSlots > 0) then
  468.     RowSlot^[CurrentRecord mod NumSlots].RowNum := EmptySlot;
  469.   TDmxEditor.SetUpRecord;
  470.   RedrawRecord := TRUE;
  471.   Appending    := NewRecord;
  472. end;
  473.  
  474.  
  475. procedure TDmxEditBuf.Store(var S: TStream);
  476. begin
  477.   TDmxEditor.Store(S);
  478.   S.Write(KeyFields,  sizeof(KeyFields));
  479.   S.Write(Expandable, sizeof(Expandable));
  480.   S.Write(StepMode,   sizeof(StepMode));
  481. end;
  482.  
  483.  
  484. function  TDmxEditBuf.WriteRec(var RecData ) : boolean;
  485. { abstract virtual method to write a record }
  486. begin
  487.   Abstract;
  488.  { This method should write a record and return TRUE if there is no error. }
  489. end;
  490.  
  491.  
  492. function TDmxEditBuf.Valid(Command: word) : boolean;
  493. begin
  494.   If (Command = cmDMX_ZeroizeRecord) and (not RecordSelected) then
  495.     Valid := FALSE
  496.    else
  497.     Valid := TDmxEditor.Valid(Command);
  498. end;
  499.  
  500.  
  501. procedure TDmxEditBuf.ZeroizeField(Whole: boolean; Field: pDMXfieldrec);
  502. begin
  503.   TDmxEditor.ZeroizeField(Whole, Field);
  504.   If (Field <> nil) and (Field^.fieldnum in KeyFields) then KeyAltered := TRUE;
  505. end;
  506.  
  507.  
  508. procedure TDmxEditBuf.ZeroizeRecord;
  509. var  FS    : boolean;
  510. begin
  511.   If not RecordSelected then Exit;
  512.   TDmxEditor.ZeroizeRecord;
  513.   If Appending then
  514.     begin
  515.     RecordAltered := FALSE;
  516.     FieldAltered  := FALSE;
  517.     If FieldSelected then
  518.       begin
  519.       EvaluateField;
  520.       SetupField;
  521.       end;
  522.     end
  523.    else
  524.     begin
  525.     FS := FieldSelected;
  526.     If FS then EvaluateField;
  527.     Appending := TRUE;
  528.     RecordAltered := FALSE;
  529.     FieldAltered  := FALSE;
  530.     KeyAltered := TRUE;
  531.     DeleteRec;
  532.     EvaluateRecord;
  533.     ResetSize;
  534.     DrawView;
  535.     SetupRecord;
  536.     If FS then SetupField;
  537.     end;
  538. end;
  539.  
  540.  
  541.   { ══ TDmxStreamBuf ═════════════════════════════════════════════════════ }
  542.  
  543.  
  544. function  TDmxStreamBuf.ErrorFunc : boolean;
  545. { virtual method to handle stream errors }
  546. begin
  547.   ErrorFunc := TDmxEditBuf.ErrorFunc;
  548.   PStream(WorkingData)^.Reset;
  549. end;
  550.  
  551.  
  552. procedure TDmxStreamBuf.LoadStruct(var S: TStream);
  553. begin
  554.   TDmxEditBuf.LoadStruct(S);
  555.   S.Read(PrefixSize, sizeof(PrefixSize));
  556.   Prefix := nil;
  557. end;
  558.  
  559.  
  560. function  TDmxStreamBuf.ReadRec(var RecData ) : boolean;
  561. begin
  562.   With PStream(WorkingData)^ do
  563.     begin
  564.     If (Status <> stOk) then Reset;
  565.     Read(RecData, RecordSize);
  566.     ReadRec := (Status = stOk);
  567.     end;
  568. end;
  569.  
  570.  
  571. function  TDmxStreamBuf.RecordLimit : longint;
  572. var L : longint;
  573. begin
  574.   If (RecordSize = 0) then
  575.     RecordLimit := 0
  576.    else
  577.     begin
  578.     L := (PStream(WorkingData)^.GetSize - PrefixSize) div RecordSize;
  579.     RecordLimit := L;
  580.     end;
  581. end;
  582.  
  583.  
  584. function  TDmxStreamBuf.SeekEnd : boolean;
  585. var  L : longint;
  586. begin
  587.   L := RecordLimit;
  588.   PStream(WorkingData)^.Seek(PrefixSize + (L * RecordSize));
  589.   SeekEnd := (PStream(WorkingData)^.Status = stOk);
  590. end;
  591.  
  592.  
  593. function  TDmxStreamBuf.SeekRec(RecNum: longint) : boolean;
  594. var  L,L2,RSize : longint;
  595. begin
  596.   PStream(WorkingData)^.Reset;
  597.   L := RecNum;
  598.   RSize := RecordSize;
  599.   L := L * RSize;
  600.   L2 := PrefixSize;
  601.   L := L + L2;
  602.   PStream(WorkingData)^.Seek(L);
  603.   SeekRec := (PStream(WorkingData)^.Status = stOk);
  604. end;
  605.  
  606.  
  607. procedure TDmxStreamBuf.StoreStruct(var S: TStream);
  608. begin
  609.   TDmxEditBuf.StoreStruct(S);
  610.   S.Write(PrefixSize, sizeof(PrefixSize));
  611. end;
  612.  
  613.  
  614. function  TDmxStreamBuf.WriteRec(var RecData ) : boolean;
  615. begin
  616.   With PStream(WorkingData)^ do
  617.     begin
  618.     If (Status <> stOk) then Reset;
  619.     Write(RecData, RecordSize);
  620.     WriteRec := (Status = stOk);
  621.     end;
  622. end;
  623.  
  624.  
  625.   { ══ TDmxExpRecInd ═════════════════════════════════════════════════════ }
  626.  
  627.  
  628. procedure TDmxExpRecInd.Draw;
  629. var  i      : integer;
  630.      A,E  : string[80];
  631.      B      : TDrawBuffer;
  632.      C      : word;
  633. begin
  634.   If (Link = nil) then
  635.     TView.Draw
  636.    else
  637.     begin
  638.     C := GetColor(6);
  639.     MoveChar(B, '═', C, Size.X);
  640.     Str(succ(Link^.CurrentRecord):1, A);
  641.     i := Link^.Limit.Y;
  642.     If PDmxEditBuf(Link)^.Expandable then
  643.       begin
  644.       Dec(i);
  645.       If Link^.CurrentRecord = pred(Link^.Limit.Y) then A := 'Add';
  646.       end;
  647.     Str(i:1, E);
  648.     A := A + '/' + E;
  649.     If length(A) > Size.X then A[0] := chr(length(A) - succ(length(E)));
  650.     If length(A) > Size.X then
  651.       MoveChar(B, showOVERFLOW, C, Size.X)
  652.      else
  653.       begin
  654.       If length(A) < Size.X then A := A + ' ';
  655.       If length(A) < Size.X then A := ' ' + A;
  656.       MoveStr(B[succ((Size.X) - length(A)) shr 1], A, C);
  657.       end;
  658.     WriteBuf(0, 0, Size.X, 1, B);
  659.     end;
  660. end;
  661.  
  662.  
  663.   { ══ TDmxExpBuf ════════════════════════════════════════════════════════ }
  664.  
  665.  
  666. procedure TDmxExpBuf.InitData(var AData );
  667. begin
  668.   TDmxStreamBuf.InitData(AData);
  669.   PrefixSize    := DataBlockSize;
  670.   Expandable    := TRUE;
  671.   ResetSize;
  672. end;
  673.  
  674.  
  675.   { ══ TDmxBufWin ════════════════════════════════════════════════════════ }
  676.  
  677.  
  678. procedure TDmxBufWin.InitDMX(ATemplate: string;  var AData;
  679.                  ALabels,ARecInd: PDmxLink;  BSize: longint);
  680. var  R    : TRect;
  681. begin
  682.   GetExtent(R);
  683.   R.Grow(-1,-1);
  684.   If (ALabels <> nil) then Inc(R.A.Y, ALabels^.Size.Y);
  685.  
  686.   Insert(New(PDmxStreamBuf, Init(ATemplate, AData, BSize, R,
  687.                 ALabels, ARecInd,
  688.                 StandardScrollBar(sbHorizontal+ sbHandleKeyboard),
  689.                 StandardScrollBar(sbVertical  + sbHandleKeyboard))));
  690.  
  691. end;
  692.  
  693.  
  694.   { ══ TDmxExpBufWin ═════════════════════════════════════════════════════ }
  695.  
  696.  
  697. procedure TDmxExpBufWin.InitDMX(ATemplate: string;  var AData;
  698.                 ALabels,ARecInd: PDmxLink;  BSize: longint);
  699. var  R    : TRect;
  700. begin
  701.   GetExtent(R);
  702.   R.Grow(-1,-1);
  703.   Inc(R.A.Y, 2);
  704.  
  705.   DMX := New(PDmxExpBuf, Init(ATemplate, AData, BSize, R,
  706.                 ALabels, ARecInd,
  707.                 StandardScrollBar(sbHorizontal+ sbHandleKeyboard),
  708.                 StandardScrollBar(sbVertical  + sbHandleKeyboard)));
  709.  
  710. end;
  711.  
  712.  
  713. function  TDmxExpBufWin.NewRecInd(Len: integer) : PDmxLink;
  714. begin
  715.   If Len <= 0 then
  716.     NewRecInd := nil
  717.    else
  718.     NewRecInd := New(PDmxExpRecInd, InitInsert(@Self, Len));
  719. end;
  720.  
  721.  
  722.   { ══ TDmxEditRecBuf ════════════════════════════════════════════════════ }
  723.  
  724.  
  725. function  TDmxEditRecBuf.AppendRec(var RecData ) : boolean;
  726. { abstract virtual method to write a record }
  727. begin
  728.   Abstract;
  729.  { This method must append a record and return TRUE if there is no error. }
  730. end;
  731.  
  732.  
  733. function  TDmxEditRecBuf.FirstRec : boolean;
  734. { pseudo-abstract method to seek to the first record position }
  735. begin
  736.  { This method should be overridden to seek directly to the
  737.    first record, and it should return TRUE if there is no error.
  738.    The default method just repeats PrevRec() until it receives
  739.    an error.
  740.   }
  741.   Repeat until not PrevRec;
  742.   FirstRec := TRUE;
  743. end;
  744.  
  745.  
  746. procedure TDmxEditRecBuf.InitData(var AData );
  747. begin
  748.   TDmxEditBuf.InitData(AData);
  749.   StepMode := TRUE;
  750. end;
  751.  
  752.  
  753. function  TDmxEditRecBuf.LastRec : boolean;
  754. { abstract virtual method to seek to the last record position }
  755. begin
  756.   Abstract;
  757.  { This method must be overridden to seek to the last record
  758.    position, and it should return TRUE if there is no error.
  759.   }
  760. end;
  761.  
  762.  
  763. function  TDmxEditRecBuf.NextRec : boolean;
  764. { abstract virtual method to seek to the next record position }
  765. begin
  766.   Abstract;
  767.  { This method must be overridden to seek to the next record
  768.    position, and it should return TRUE if there is no error.
  769.   }
  770. end;
  771.  
  772.  
  773. function  TDmxEditRecBuf.PrevRec : boolean;
  774. { abstract virtual method to seek to the previous record position }
  775. begin
  776.  { This method must be overridden to seek to the previous record
  777.    position, and it should return TRUE if there is no error.
  778.   }
  779. end;
  780.  
  781.  
  782. function  TDmxEditRecBuf.SeekEnd : boolean;
  783. begin
  784.   SeekEnd := TRUE;
  785. end;
  786.  
  787.  
  788. function  TDmxEditRecBuf.SeekRec(RecNum: longint) : boolean;
  789. { uses FirstRec(), LastRec(), NextRec() and PrevRec() to seek to a record }
  790. var  B        : boolean;
  791.      EndNum : longint;
  792.     function  LastRecord : boolean;
  793.     begin
  794.       If (RecordSize = 0) then
  795.     begin
  796.     EndNum := 0;
  797.     LastRecord := FALSE;
  798.     end
  799.        else
  800.     begin
  801.     EndNum := (DataBlockSize div RecordSize) - 1;
  802.     If Expandable then Dec(EndNum);
  803.     LastRecord := (RecNum = EndNum);
  804.     end;
  805.     end;
  806. begin
  807.   B := TRUE;
  808.   If (RecNum = 0) then
  809.     begin
  810.     B := FirstRec;
  811.     RecPosition := 0;
  812.     end
  813.    else
  814.     If LastRecord then
  815.       begin
  816.       B := LastRec;
  817.       RecPosition := EndNum;
  818.       end
  819.      else
  820.       begin
  821.       While (RecPosition < RecNum) and B do
  822.     begin
  823.     B := NextRec;
  824.     If B then Inc(RecPosition);
  825.     end;
  826.       While (RecPosition > RecNum) and B do
  827.     begin
  828.     B := PrevRec;
  829.     If B then Dec(RecPosition);
  830.     end;
  831.       end;
  832.   SeekRec := B;
  833. end;
  834.  
  835.  
  836. function  TDmxEditRecBuf.UpdateRec(var RecData ) : boolean;
  837. { abstract virtual method to update the current record }
  838. begin
  839.   Abstract;
  840.  { This method must write a record and return TRUE if there is no error. }
  841. end;
  842.  
  843.  
  844. function  TDmxEditRecBuf.WriteRec(var RecData ) : boolean;
  845. { virtual method to write a record }
  846. begin
  847.   If Appending then
  848.     begin
  849.     KeyAltered := (KeyFields <>[]);
  850.     WriteRec := AppendRec(RecData);
  851.     end
  852.    else
  853.     WriteRec := UpdateRec(RecData);
  854. end;
  855.  
  856.  
  857.   { ══════════════════════════════════════════════════════════════════════ }
  858.  
  859.  
  860. procedure RegisterTVDMXBUF;
  861. begin
  862.   RegisterType(RDmxStreamBuf);
  863.   RegisterType(RDmxExpBuf);
  864.   RegisterType(RDmxExpRecInd);
  865.   RegisterType(RDmxBufWin);
  866.   RegisterType(RDmxExpBufWin);
  867. end;
  868.  
  869.  
  870.   { ══════════════════════════════════════════════════════════════════════ }
  871.  
  872.  
  873.  
  874. End.
  875.